package com.lonely.goods.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.lonely.api.mes.model.dto.SynchronizedStyleDTO;
import com.lonely.api.mes.service.ISynchronizedMesService;
import com.lonely.common.constant.GoodsConstants;
import com.lonely.common.core.domain.BaseEntity;
import com.lonely.common.core.domain.Select;
import com.lonely.common.core.page.Condition;
import com.lonely.common.enums.CommonStatus;
import com.lonely.common.utils.FzzfDateUtil;
import com.lonely.common.utils.JsonUtil;
import com.lonely.common.utils.SecurityUtils;
import com.lonely.goods.domain.dto.goods.*;
import com.lonely.goods.domain.entity.*;
import com.lonely.goods.domain.vo.goods.*;
import com.lonely.goods.enums.GoodsEnum;
import com.lonely.goods.mapper.SysGoodsMapper;
import com.lonely.goods.service.*;
import com.lonely.inventory.domain.entity.SysInventoryStorageArchive;
import com.lonely.inventory.service.IStorageArchiveService;
import com.lonely.order.domain.vo.order.OrderQuantityInfo;
import com.lonely.order.service.IOrderService;
import com.lonely.order.utils.GeneratorUtil;
import com.lonely.system.domain.entity.SysUser;
import com.lonely.system.service.ISysUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: 黄志标
 * @date: 2025/6/25 15:42
 * @description: 打版接口实现
 */
@Service
public class GoodsServiceImpl extends ServiceImpl<SysGoodsMapper, SysGoods> implements IGoodsService {

    @Autowired
    private IGoodsFileService goodsFileService;

    @Autowired
    private IGoodsPartService goodsPartService;

    @Autowired
    private IGoodsNotesService goodsNotesService;

    @Autowired
    private IGoodsPartMaterialService goodsPartMaterialService;

    @Autowired
    private IGoodsSecondProcessService goodsSecondProcessService;

    @Autowired
    private IGoodsProcessService goodsProcessService;

    @Autowired
    private IOrderService orderService;

    @Autowired
    private IGoodsLogService goodsLogService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private IStorageArchiveService storageArchiveService;

    @Autowired
    private ISynchronizedMesService synchronizedMesService;

    /**
     * 分页查询
     *
     * @param queryDto
     * @return
     */
    @Override
    public Page<QueryGoodsPageVO> page(QueryGoodsPageDTO queryDto) {

        // 打版交期处理
        Date patternMakingDeliveryStartTime = null;
        Date patternMakingDeliveryEndTime = null;
        if (StrUtil.isNotBlank(queryDto.getPatternMakingDeliveryStartTime()) && StrUtil.isNotBlank(queryDto.getPatternMakingDeliveryEndTime())) {
            patternMakingDeliveryStartTime = DateUtil.parse(queryDto.getPatternMakingDeliveryStartTime() + " 00:00:00", "yyyy-MM-dd HH:mm:ss");
            patternMakingDeliveryEndTime = DateUtil.parse(queryDto.getPatternMakingDeliveryEndTime() + " 23:59:59", "yyyy-MM-dd HH:mm:ss");
        }

        // 预计上架时间处理
        Date expectedShelfStartTime = null;
        Date expectedShelfEndTime = null;
        if (StrUtil.isNotBlank(queryDto.getExpectedShelfStartTime()) && StrUtil.isNotBlank(queryDto.getExpectedShelfEndTime())) {
            expectedShelfStartTime = DateUtil.parse(queryDto.getExpectedShelfStartTime() + " 00:00:00", "yyyy-MM-dd HH:mm:ss");
            expectedShelfEndTime = DateUtil.parse(queryDto.getExpectedShelfEndTime() + " 23:59:59", "yyyy-MM-dd HH:mm:ss");
        }

        // 实际上架时间处理
        Date actualShelfStartTime = null;
        Date actualShelfEndTime = null;
        if (StrUtil.isNotBlank(queryDto.getActualShelfStartTime()) && StrUtil.isNotBlank(queryDto.getActualShelfEndTime())) {
            actualShelfStartTime = DateUtil.parse(queryDto.getActualShelfStartTime() + " 00:00:00", "yyyy-MM-dd HH:mm:ss");
            actualShelfEndTime = DateUtil.parse(queryDto.getActualShelfEndTime() + " 23:59:59", "yyyy-MM-dd HH:mm:ss");
        }

        // 批量skc处理
        queryDto.setBatchSkcs(Optional.ofNullable(queryDto.getBatchSkcs()).orElse(new ArrayList<>())
                .stream().filter(StrUtil::isNotBlank).collect(Collectors.toList()));
        if (CollUtil.isNotEmpty(queryDto.getBatchSkcs())) {
            queryDto.setSkc(null);
        }

        Page<SysGoods> page = Condition.page(queryDto);
        page = super.page(page, new LambdaQueryWrapper<SysGoods>()
                .eq(StrUtil.isNotBlank(queryDto.getDesignCode()), SysGoods::getDesignCode, queryDto.getDesignCode())
                .eq(StrUtil.isNotBlank(queryDto.getSkc()), SysGoods::getSkc, queryDto.getSkc())
                .in(CollUtil.isNotEmpty(queryDto.getBatchSkcs()), SysGoods::getSkc, queryDto.getBatchSkcs())
                .like(StrUtil.isNotBlank(queryDto.getBrand()), SysGoods::getBrand, queryDto.getBrand())
                .like(StrUtil.isNotBlank(queryDto.getSeries()), SysGoods::getSeries, queryDto.getSeries())
                .like(StrUtil.isNotBlank(queryDto.getDesigner()), SysGoods::getDesigner, queryDto.getDesigner())
                .between(patternMakingDeliveryStartTime != null, SysGoods::getPatternMakingDeliveryTime, patternMakingDeliveryStartTime, patternMakingDeliveryEndTime)
                .between(expectedShelfStartTime != null, SysGoods::getExpectedShelfTime, expectedShelfStartTime, expectedShelfEndTime)
                .between(actualShelfStartTime != null, SysGoods::getActualShelfTime, actualShelfStartTime, actualShelfEndTime)
                .orderByDesc(SysGoods::getCreateTime)
        );

        Page<QueryGoodsPageVO> resultPage = new Page<>();
        BeanUtils.copyProperties(page, resultPage);
        if (CollUtil.isNotEmpty(page.getRecords())) {

            // 商品备注映射
            List<Long> goodsIds = page.getRecords().stream().map(BaseEntity::getId).distinct().collect(Collectors.toList());
            Map<Long, List<SysGoodsNotes>> goodsNotesMap = new HashMap<>();
            if (CollUtil.isNotEmpty(goodsIds)) {
                goodsNotesMap.putAll(this.goodsNotesService.list(new LambdaQueryWrapper<SysGoodsNotes>()
                                .in(SysGoodsNotes::getGoodsId, goodsIds)
                                .eq(SysGoodsNotes::getStatus, CommonStatus.ENABLE.code))
                        .stream().collect(Collectors.groupingBy(SysGoodsNotes::getGoodsId)));
            }

            // 查询设计师id对应的名字
            List<Long> designers = page.getRecords().stream().map(SysGoods::getDesigner).filter(StrUtil::isNotBlank)
                    .map(Convert::toLong)
                    .distinct().collect(Collectors.toList());
            Map<Long, String> designerNameMap = new HashMap<>();
            if (CollUtil.isNotEmpty(designers)) {
                designerNameMap.putAll(this.userService.listByIds(designers).stream().collect(Collectors.toMap(BaseEntity::getId, SysUser::getNickName, (a, b) -> b)));
            }

            // 商品库位映射
            List<Long> inventoryStorageArchiveIds = page.getRecords().stream().map(SysGoods::getInventoryStorageArchiveId).filter(Objects::nonNull).collect(Collectors.toList());
            Map<Long, String> storageArchiveNameMap = new HashMap<>();
            if (CollUtil.isNotEmpty(inventoryStorageArchiveIds)) {
                storageArchiveNameMap.putAll(this.storageArchiveService.listByIds(inventoryStorageArchiveIds).stream().collect(Collectors.toMap(BaseEntity::getId, SysInventoryStorageArchive::getStorageName)));
            }

            resultPage.setRecords(page.getRecords().stream().map(x -> {
                QueryGoodsPageVO queryGoodsPageVO = new QueryGoodsPageVO();
                BeanUtils.copyProperties(x, queryGoodsPageVO);

                // 设置备注信息
                if (goodsNotesMap.containsKey(x.getId())) {
                    List<String> notes = Optional.ofNullable(goodsNotesMap.get(x.getId())).orElse(new ArrayList<>())
                            .stream().map(SysGoodsNotes::getNotes)
                            .collect(Collectors.toList());
                    queryGoodsPageVO.setNotes(notes);
                }

                // 设置日期
                queryGoodsPageVO.setPatternMakingDeliveryTime(DateUtil.formatDate(x.getPatternMakingDeliveryTime()));
                queryGoodsPageVO.setExpectedShelfTime(DateUtil.formatDate(x.getExpectedShelfTime()));
                queryGoodsPageVO.setActualShelfTime(DateUtil.formatDate(x.getActualShelfTime()));

                // 设置状态名称
                queryGoodsPageVO.setStatusName(GoodsEnum.GoodsStatusEnum.getByStatus(x.getStatus()).getDesc());

                // 设置设计师名字
                if (StrUtil.isNotBlank(x.getDesigner())) {
                    queryGoodsPageVO.setDesignerName(designerNameMap.get(Convert.toLong(x.getDesigner())));
                }

                // 设置库位名称
                if (x.getInventoryStorageArchiveId() != null && storageArchiveNameMap.containsKey(x.getInventoryStorageArchiveId())) {
                    queryGoodsPageVO.setInventoryStorageArchiveName(storageArchiveNameMap.get(x.getInventoryStorageArchiveId()));
                }

                return queryGoodsPageVO;
            }).collect(Collectors.toList()));
        }
        return resultPage;
    }

    /**
     * 添加新商品
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addGoods() {
        SysGoods sysGoods = new SysGoods();
        sysGoods.setDesignCode(GeneratorUtil.generatorDesignCode());
        sysGoods.setSkc(GeneratorUtil.generatorSkc());
        sysGoods.setPic(GoodsConstants.DEFAULT_GOODS_PIC);
        sysGoods.setFactoryId(SecurityUtils.getFactoryId());
        sysGoods.setCreateBy(SecurityUtils.getUserId());
        sysGoods.setUpdateBy(SecurityUtils.getUserId());
        super.save(sysGoods);

        // 初始化一个默认的非套装的部件
//        this.goodsPartService.initNoSuitPart(sysGoods.getId());
    }

    /**
     * 根据商品id获取商品款信息
     *
     * @param goodsId
     * @return
     */
    @Override
    public GoodsDesignInfoVO getGoodsDesignInfo(Long goodsId) {
        SysGoods goods = super.getById(goodsId);
        Assert.notNull(goods, "商品不存在");

        GoodsDesignInfoVO goodsDesignInfoVO = new GoodsDesignInfoVO();
        BeanUtils.copyProperties(goods, goodsDesignInfoVO);

        if (StrUtil.isEmpty(goods.getColors())) {
            goodsDesignInfoVO.setColors(new ArrayList<>());
        } else {
            goodsDesignInfoVO.setColors(JSON.parseArray(goods.getColors(), String.class));
        }

        goodsDesignInfoVO.setAvailableSizes(JsonUtil.parseArray(goods.getSize(), String.class));
        goodsDesignInfoVO.setExpectedShelfTime(DateUtil.formatDate(goods.getExpectedShelfTime()));
        goodsDesignInfoVO.setPatternMakingDeliveryTime(DateUtil.formatDate(goods.getPatternMakingDeliveryTime()));
        goodsDesignInfoVO.setActualShelfTime(DateUtil.formatDate(goods.getActualShelfTime()));

        // 查询商品对应的文件信息
        List<SysGoodsFile> files = this.goodsFileService.list(new LambdaQueryWrapper<SysGoodsFile>()
                .eq(SysGoodsFile::getGoodsId, goodsId)
                .in(SysGoodsFile::getType, Lists.newArrayList(GoodsEnum.GoodsFileTypeEnum.PATTERN_MAKING_BEFORE.getType(),
                        GoodsEnum.GoodsFileTypeEnum.PATTERN_MAKING_AFTER.getType(),
                        GoodsEnum.GoodsFileTypeEnum.PAPER_PATTERN.getType())));
        if (CollUtil.isNotEmpty(files)) {
            goodsDesignInfoVO.setPatternMakingBeforeFiles(files.stream().filter(x -> x.getType().equals(GoodsEnum.GoodsFileTypeEnum.PATTERN_MAKING_BEFORE.getType())).map(x -> {
                GoodsFileDTO goodsFileDTO = new GoodsFileDTO();
                goodsFileDTO.setId(StrUtil.toString(x.getId()));
                goodsFileDTO.setName(x.getName());
                goodsFileDTO.setUrl(x.getUrl());
                return goodsFileDTO;
            }).collect(Collectors.toList()));

            goodsDesignInfoVO.setPatternMakingAfterFiles(files.stream().filter(x -> x.getType().equals(GoodsEnum.GoodsFileTypeEnum.PATTERN_MAKING_AFTER.getType())).map(x -> {
                GoodsFileDTO goodsFileDTO = new GoodsFileDTO();
                goodsFileDTO.setId(StrUtil.toString(x.getId()));
                goodsFileDTO.setName(x.getName());
                goodsFileDTO.setUrl(x.getUrl());
                return goodsFileDTO;
            }).collect(Collectors.toList()));

            goodsDesignInfoVO.setPaperPatternFiles(files.stream().filter(x -> x.getType().equals(GoodsEnum.GoodsFileTypeEnum.PAPER_PATTERN.getType())).map(x -> {
                GoodsFileDTO goodsFileDTO = new GoodsFileDTO();
                goodsFileDTO.setId(StrUtil.toString(x.getId()));
                goodsFileDTO.setName(x.getName());
                goodsFileDTO.setUrl(x.getUrl());
                return goodsFileDTO;
            }).collect(Collectors.toList()));
        }


        // 对应商品部件信息
        goodsDesignInfoVO.setGoodsParts(this.goodsPartService.list(new LambdaQueryWrapper<SysGoodsPart>()
                        .eq(SysGoodsPart::getGoodsId, goodsId))
                .stream().map(x -> {
                    GoodsPartDTO goodsPartDTO = new GoodsPartDTO();
                    BeanUtils.copyProperties(x, goodsPartDTO);
                    return goodsPartDTO;
                }).collect(Collectors.toList()));

        return goodsDesignInfoVO;
    }

    /**
     * 修改商品款信息
     *
     * @param submitDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitDesignInfo(GoodsDesignInfoSubmitDTO submitDTO) {
        Assert.notNull(submitDTO.getId(), "商品id不能为空");
        SysGoods sysGoods = super.getById(submitDTO.getId());
        Assert.notNull(sysGoods, "商品不存在");

        //1. 数据校验
        this.checkGoodsDesignInfo(submitDTO);

        // 2. 文件列表处理
        this.goodsFileService.submitGoodsDesignInfoFiles(submitDTO);

        //3. 处理商品部件信息
        this.goodsPartService.submitGoodsDesignInfoParts(submitDTO);

        // 3. 商品信息处理
        BeanUtils.copyProperties(submitDTO, sysGoods);
        sysGoods.setSize(JsonUtil.toJsonString(submitDTO.getAvailableSizes()));
        sysGoods.setPatternMakingDeliveryTime(FzzfDateUtil.parseDate(submitDTO.getPatternMakingDeliveryTime()));
        sysGoods.setExpectedShelfTime(FzzfDateUtil.parseDate(submitDTO.getExpectedShelfTime()));
//        sysGoods.setActualShelfTime(FzzfDateUtil.parseDate(submitDTO.getActualShelfTime()));
        sysGoods.setColors(JsonUtil.toJsonString(submitDTO.getColors()));
        sysGoods.setCustomerId(null);

        // 主图处理
        if (CollUtil.isNotEmpty(submitDTO.getPatternMakingAfterFiles())) {
            sysGoods.setPic(submitDTO.getPatternMakingAfterFiles().get(0).getUrl());
        } else if (CollUtil.isNotEmpty(submitDTO.getPatternMakingBeforeFiles())) {
            sysGoods.setPic(submitDTO.getPatternMakingBeforeFiles().get(0).getUrl());
        } else {
            sysGoods.setPic(GoodsConstants.DEFAULT_GOODS_PIC);
        }

        sysGoods.setStatus(GoodsEnum.GoodsStatusEnum.NEW_MAINTENANCE_INFORMATION.getStatus());
        sysGoods.setFactoryId(SecurityUtils.getFactoryId());
        sysGoods.setUpdateBy(SecurityUtils.getUserId());
        super.updateById(sysGoods);
    }

    /**
     * 根据商品id获取商品报价单信息
     *
     * @param goodsId
     * @return
     */
    @Override
    public GoodsQuotationSheetVO getGoodsQuotationSheet(Long goodsId) {

        // 查询商品id对应的部件信息
        GoodsQuotationSheetVO goodsQuotationSheetVO = new GoodsQuotationSheetVO();
        goodsQuotationSheetVO.setId(goodsId);

        List<GoodsQuotationSheetPartDTO> quotationSheetParts = this.goodsPartService.queryQuotationSheetPartDetail(goodsId);
        goodsQuotationSheetVO.setParts(quotationSheetParts);

        Map<Long, String> partIdNameMap = quotationSheetParts.stream().collect(Collectors.toMap(GoodsQuotationSheetPartDTO::getPartId, GoodsQuotationSheetPartDTO::getPartLibrary));

        // 成本统计
        List<GoodsQuotationSheetTotalCastVO> totalCasts = new ArrayList<>();
        List<GoodsQuotationSheetTotalCastVO> partTotalCasts = new ArrayList<>();
        for (GoodsQuotationSheetPartDTO currentPart : quotationSheetParts) {

            // 当前部件的当前颜色的物料总和
            for (GoodsQuotationSheetPartMaterialDTO currentPartColorMaterial : currentPart.getPartMaterials()) {
                // 当前部件的成本统计
                GoodsQuotationSheetTotalCastVO currentPartTotalCast = new GoodsQuotationSheetTotalCastVO();
                currentPartTotalCast.setType(GoodsEnum.GoodsTotalCostTypeEnum.PART.getType());
                currentPartTotalCast.setPartId(currentPart.getPartId());
                currentPartTotalCast.setPartColor(currentPartColorMaterial.getGoodsColor());

                // 当前部件的加工费用
                BigDecimal processingCost;
                if (currentPart.getPartProcess() == null || StrUtil.isBlank(currentPart.getPartProcess().getTotalProcessCosts())) {
                    processingCost = new BigDecimal(0);
                } else {
                    processingCost = new BigDecimal(currentPart.getPartProcess().getTotalProcessCosts());
                }
                processingCost = NumberUtil.round(processingCost, 2);

                // 当前部件的物料金额总和
                BigDecimal materialCost = currentPartColorMaterial.getMaterials().stream()
                        .map(x -> {
                            if (StrUtil.isBlank(x.getAmount())) {
                                return new BigDecimal(0);
                            }
                            return new BigDecimal(x.getAmount());
                        })
                        .reduce(new BigDecimal(0), BigDecimal::add);
                materialCost = NumberUtil.round(materialCost, 2);

                // 总价
                BigDecimal totalPrice = NumberUtil.round(NumberUtil.add(processingCost, materialCost), 2);

                currentPartTotalCast.setTotalPrice(totalPrice.toPlainString());
                currentPartTotalCast.setMaterialCost(materialCost.toPlainString());
                currentPartTotalCast.setProcessingCost(processingCost.toPlainString());
                currentPartTotalCast.setOtherExpenses(null);
                currentPartTotalCast.setPartName(String.format("%s(%s)", currentPart.getPartLibrary(), currentPartColorMaterial.getGoodsColor()));

                partTotalCasts.add(currentPartTotalCast);
                totalCasts.add(currentPartTotalCast);
            }

//            // 当前部件的物料金额总和
//            BigDecimal materialCost = currentPart.getPartMaterials().stream().flatMap(x -> x.getMaterials().stream())
//                    .map(x -> {
//                        if (StrUtil.isBlank(x.getAmount())) {
//                            return new BigDecimal(0);
//                        }
//                        return new BigDecimal(x.getAmount());
//                    })
//                    .reduce(new BigDecimal(0), BigDecimal::add);
//            materialCost = NumberUtil.round(materialCost, 2);

        }


        // 处理总计
        LinkedHashMap<Long, List<GoodsQuotationSheetTotalCastVO>> partTotalCastMap = partTotalCasts.stream()
                .collect(Collectors.groupingBy(GoodsQuotationSheetTotalCastVO::getPartId, LinkedHashMap::new,
                        Collectors.toList()));

        partTotalCastMap.forEach((partId, partTotalCastList) -> {
            GoodsQuotationSheetTotalCastVO currentPartTotalCast = new GoodsQuotationSheetTotalCastVO();
            currentPartTotalCast.setType(GoodsEnum.GoodsTotalCostTypeEnum.TOTAL_COST.getType());
            currentPartTotalCast.setPartId(partId);
            currentPartTotalCast.setPartColor(null);
            currentPartTotalCast.setPartName(String.format("%s-总价", MapUtil.getStr(partIdNameMap, partId)));

            BigDecimal totalPrice = partTotalCastList.stream().map(x -> new BigDecimal(x.getTotalPrice()))
                    .reduce(new BigDecimal(0), BigDecimal::add);
            totalPrice = NumberUtil.round(totalPrice, 2);
            currentPartTotalCast.setTotalPrice(totalPrice.toPlainString());

            BigDecimal materialCost = partTotalCastList.stream().map(x -> new BigDecimal(x.getMaterialCost()))
                    .reduce(new BigDecimal(0), BigDecimal::add);
            materialCost = NumberUtil.round(materialCost, 2);
            currentPartTotalCast.setMaterialCost(materialCost.toPlainString());

            BigDecimal processingCost = partTotalCastList.stream().map(x -> new BigDecimal(x.getProcessingCost()))
                    .reduce(new BigDecimal(0), BigDecimal::add);
            processingCost = NumberUtil.round(processingCost, 2);
            currentPartTotalCast.setProcessingCost(processingCost.toPlainString());
            currentPartTotalCast.setOtherExpenses(null);
            totalCasts.add(currentPartTotalCast);
        });


//        // 总计
//        GoodsQuotationSheetTotalCastVO totalCastVO = new GoodsQuotationSheetTotalCastVO();
//        totalCastVO.setType(GoodsEnum.GoodsTotalCostTypeEnum.TOTAL_COST.getType());
//        totalCastVO.setPartId(0L);
//        totalCastVO.setPartColor(null);
//        totalCastVO.setPartName("总价");
//
//        BigDecimal totalPrice = partTotalCasts.stream().map(x -> new BigDecimal(x.getTotalPrice()))
//                .reduce(new BigDecimal(0), BigDecimal::add);
//        totalPrice = NumberUtil.round(totalPrice, 2);
//        totalCastVO.setTotalPrice(totalPrice.toPlainString());
//
//        BigDecimal materialCost = partTotalCasts.stream().map(x -> new BigDecimal(x.getMaterialCost()))
//                .reduce(new BigDecimal(0), BigDecimal::add);
//        materialCost = NumberUtil.round(materialCost, 2);
//        totalCastVO.setMaterialCost(materialCost.toPlainString());
//
//        BigDecimal processingCost = partTotalCasts.stream().map(x -> new BigDecimal(x.getProcessingCost()))
//                .reduce(new BigDecimal(0), BigDecimal::add);
//        processingCost = NumberUtil.round(processingCost, 2);
//        totalCastVO.setProcessingCost(processingCost.toPlainString());
//        totalCastVO.setOtherExpenses(null);
//        totalCasts.add(totalCastVO);


        goodsQuotationSheetVO.setTotalCasts(totalCasts);
        return goodsQuotationSheetVO;
    }

    /**
     * 修改商品报价单
     *
     * @param submitDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitQuotationSheet(GoodsQuotationSheetSubmitDTO submitDTO) {
        SysGoods sysGoods = super.getById(submitDTO.getId());
        Assert.notNull(sysGoods, "商品不存在");

        // 处理 商品部件物料信息
        this.goodsPartMaterialService.submitGoodsQuotationSheetPartsMaterial(submitDTO);

        // 处理 商品二次工艺
        this.goodsSecondProcessService.submitGoodsQuotationSheetPartsSecondProcess(submitDTO);

        // 处理 商品成衣二次工艺
        this.goodsSecondProcessService.submitGoodsQuotationSheetPartsReadyToWearSecondProcess(submitDTO);

        // 处理 商品工序
        this.goodsProcessService.submitGoodsQuotationSheetPartsProcess(submitDTO);

        // 将最新的报价单信息同步到订单中
        this.orderService.synchronizedGoodsQuotationSheetPartMaterials(sysGoods);

        // 将最新的报价单信息同步到采购单中
        //this.materialPurchaseService.synchronizedGoodsQuotationSheetPartMaterials(sysGoods);
    }

    /**
     * 复制已有bom的数据查询
     *
     * @param queryDto
     * @return
     */
    @Override
    public List<CopyBomQueryVO> copyBomDataQuery(CopyBomQueryDTO queryDto) {

        // 1. 先判断当前设计款号在本地数据库中是否存在
        SysGoods goods = super.getOne(new LambdaQueryWrapper<SysGoods>()
                .eq(SysGoods::getDesignCode, queryDto.getDesignCode())
        );
        if (goods != null) {
            return this.goodsPartService.copyBomDataQuery(goods.getId());
        }

        // 尝试从接口中心中获取
        return this.orderService.copyBomDataQuery(queryDto);
    }

    /**
     * 查询指定设计编码是否是套装
     *
     * @param designCode
     * @return
     */
    @Override
    public boolean isSuit(String designCode) {
        Assert.notBlank(designCode, "设计款号为空");

        // 1. 先判断当前设计款号在本地数据库中是否存在
        SysGoods goods = super.getOne(new LambdaQueryWrapper<SysGoods>()
                .eq(SysGoods::getDesignCode, designCode)
        );
        if (goods != null) {
            return Objects.equals(goods.getIsSuit(), 1);
        }

        //2. 尝试从接口中心中获取
        return false;
    }

    /**
     * 修改商品状态
     *
     * @param changeStatusDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeStatus(ChangeStatusDTO changeStatusDTO) {
        List<SysGoods> sysGoods = super.listByIds(changeStatusDTO.getGoodsIds());

        // 过滤掉已完成的订单
//        sysGoods = sysGoods.stream().filter(x -> !Objects.equals(x.getStatus(), GoodsEnum.GoodsStatusEnum.COMPLETED.getStatus())).collect(Collectors.toList());

        if (CollUtil.isEmpty(sysGoods)) {
            return;
        }

        GoodsEnum.GoodsStatusEnum goodsStatusEnum = GoodsEnum.GoodsStatusEnum.getByStatus(changeStatusDTO.getStatus());

        // 更新状态
        List<SysGoods> newGoods = sysGoods.stream().peek(x -> {
            x.setStatus(goodsStatusEnum.getStatus());

            // 判断状态
//            if (goodsStatusEnum == GoodsEnum.GoodsStatusEnum.COMPLETED) {
//                x.setActualShelfTime(new Date());
//            }

            x.setUpdateBy(SecurityUtils.getUserId());
        }).collect(Collectors.toList());
        super.updateBatchById(newGoods);

        // 添加操作日志
        List<SysGoodsLog> goodsLogs = newGoods.stream().map(x -> {
            SysGoodsLog sysGoodsLog = new SysGoodsLog();
            sysGoodsLog.setGoodsId(x.getId());
            sysGoodsLog.setOperatorType(GoodsEnum.GoodsLogOperatorTypeEnum.CHANGE_STATUS.getOperator());
            sysGoodsLog.setCreateBy(SecurityUtils.getUserId());
            sysGoodsLog.setUpdateBy(SecurityUtils.getUserId());
            return sysGoodsLog;
        }).collect(Collectors.toList());
        this.goodsLogService.saveBatch(goodsLogs);
    }

    /**
     * 创建订单
     *
     * @param createOrderDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createOrder(GoodsCreateOrderDTO createOrderDTO) {
        // 根据商品id获取对应数据
        SysGoods sysGoods = super.getById(createOrderDTO.getGoodsId());
        Assert.notNull(sysGoods, "商品不存在");

        // 创建订单
        this.orderService.createOrderByGoods(sysGoods, createOrderDTO);
    }

    /**
     * 基于商品id查询创建订单前的商品数据
     *
     * @param goodsId
     * @return
     */
    @Override
    public QueryGoodsByCreateOrderVO queryGoodsByCreateOrder(Long goodsId) {
        SysGoods sysGoods = super.getById(goodsId);
        Assert.notNull(sysGoods, "商品不存在");

        QueryGoodsByCreateOrderVO queryGoodsByCreateOrderVO = new QueryGoodsByCreateOrderVO();
        queryGoodsByCreateOrderVO.setId(sysGoods.getId());
        queryGoodsByCreateOrderVO.setDesignCode(sysGoods.getDesignCode());
        queryGoodsByCreateOrderVO.setSkc(sysGoods.getSkc());

        // 商品颜色下拉列表
        List<Select> colorSelects = new ArrayList<>();
        if (StrUtil.isNotBlank(sysGoods.getColors())) {
            List<String> colors = JsonUtil.parseArray(sysGoods.getColors(), String.class);
            if (CollUtil.isNotEmpty(colors)) {
                colorSelects = colors.stream().map(x -> {
                    Select select = new Select();
                    select.setValue(x);
                    select.setLabel(x);
                    return select;
                }).collect(Collectors.toList());
            }
        }
        queryGoodsByCreateOrderVO.setColorSelects(colorSelects);

        // 处理尺码表格
        if (StrUtil.isNotEmpty(sysGoods.getSize())) {
            // 商品尺码默认表格构建
            List<OrderQuantityInfo.Column> columns = new ArrayList<>();
            List<Map<String, Object>> datas = new ArrayList<>();

            // 添加默认列
            //columns.add(new OrderQuantityInfo.Column().setTitle("尺码").setKey("type"));

            List<String> sizeNames = JsonUtil.parseArray(sysGoods.getSize(), String.class);
            if (CollUtil.isNotEmpty(sizeNames)) {
                // 提取所有的尺码
                sizeNames.forEach(sizeName -> {
                    columns.add(new OrderQuantityInfo.Column().setKey(sizeName).setTitle(sizeName));
                });

                Map<String, Object> sizeData = new LinkedHashMap<>();
                //sizeData.put("type", "下单件数");

                sizeNames.forEach(currentSize -> {
                    sizeData.put(currentSize, null);
                });

                datas.add(sizeData);
            }
            queryGoodsByCreateOrderVO.setSizes(new OrderQuantityInfo().setColumns(columns).setData(datas));
        }
        return queryGoodsByCreateOrderVO;
    }


    /**
     * 根据sku获取对应的商品id
     *
     * @param sku
     * @return
     */
    @Override
    public Long getGoodsIdBySku(String sku) {
        SysGoods sysGoods = super.getOne(new LambdaQueryWrapper<SysGoods>()
                .eq(SysGoods::getSkc, sku)
        );
        Assert.notNull(sysGoods, "该SKU对应的商品不存在");
        return sysGoods.getId();
    }

    /**
     * 查询指定商品指定颜色下的总成本
     *
     * @param queryDto
     * @return
     */
    @Override
    public String queryGoodsTotalCostByColor(QueryGoodsTotalCostByColorDTO queryDto) {
        SysGoods sysGoods = super.getById(queryDto.getGoodsId());
        Assert.notNull(sysGoods, "商品不存在");

        // 获取所有报价单信息
        GoodsQuotationSheetVO goodsQuotationSheet = this.getGoodsQuotationSheet(queryDto.getGoodsId());

        // 从报价单中计算金额
        List<GoodsQuotationSheetTotalCastVO> totalCasts = goodsQuotationSheet.getTotalCasts();
        BigDecimal totalCosts = NumberUtil.add(totalCasts.stream().filter(x -> Objects.equals(x.getType(), GoodsEnum.GoodsTotalCostTypeEnum.PART.getType()))
                .filter(x -> Objects.equals(x.getPartColor(), queryDto.getColor()))
                .map(GoodsQuotationSheetTotalCastVO::getTotalPrice)
                .filter(StrUtil::isNotBlank).toArray(String[]::new));
        return NumberUtil.round(totalCosts, 2).toPlainString();
    }

    /**
     * 查询通过率
     *
     * @param queryDto
     * @return
     */
    @Override
    public QueryPassRateVO queryPassRate(QueryPassRateDTO queryDto) {
        Date startDate = DateUtil.parse(queryDto.getPassRateStartTime() + " 00:00:00", "yyyy-MM-dd HH:mm:ss");
        Date endDate = DateUtil.parse(queryDto.getPassRateEndTime() + " 23:59:59", "yyyy-MM-dd HH:mm:ss");

        //1. 获取该时间段的所有打板记录
        List<SysGoods> goodsList = super.list(new LambdaQueryWrapper<SysGoods>()
                .between(SysGoods::getReviewTime, startDate, endDate)
                .isNotNull(SysGoods::getReviewVersion)
                .ne(SysGoods::getReviewVersion, StrUtil.EMPTY)
        );
        if (CollUtil.isEmpty(goodsList)) {
            QueryPassRateVO queryPassRateVO = new QueryPassRateVO();
            queryPassRateVO.setFirstVersionPassRate("0%");
            queryPassRateVO.setSecondVersionPassRate("0%");
            queryPassRateVO.setThirdVersionPassRate("0%");
            queryPassRateVO.setFirstVersionPassCount(0);
            queryPassRateVO.setSecondVersionPassCount(0);
            queryPassRateVO.setThirdVersionPassCount(0);
            queryPassRateVO.setTotalCount(0);
            return queryPassRateVO;
        }


        int total = goodsList.size();

        //2. 分别获取每个阶段的数据
        long v1ThroughTotal = goodsList.stream().filter(x -> Objects.equals(x.getReviewVersion(), GoodsEnum.GoodsReviewVersionEnum.V1.getVersion()))
                .filter(x -> Objects.equals(x.getReviewResult(), GoodsEnum.GoodsReviewResultEnum.THROUGH.getResult()))
                .count();
        long v2ThroughTotal = goodsList.stream().filter(x -> Objects.equals(x.getReviewVersion(), GoodsEnum.GoodsReviewVersionEnum.V2.getVersion()))
                .filter(x -> Objects.equals(x.getReviewResult(), GoodsEnum.GoodsReviewResultEnum.THROUGH.getResult()))
                .count();
        long v3ThroughTotal = goodsList.stream().filter(x -> Objects.equals(x.getReviewVersion(), GoodsEnum.GoodsReviewVersionEnum.V3.getVersion()))
                .filter(x -> Objects.equals(x.getReviewResult(), GoodsEnum.GoodsReviewResultEnum.THROUGH.getResult()))
                .count();

        //3. 计算通过率
        double firstVersionPassRate = NumberUtil.div(v1ThroughTotal, total, 4);
        double secondVersionPassRate = NumberUtil.div(v2ThroughTotal, total, 4);
        double thirdVersionPassRate = NumberUtil.div(v3ThroughTotal, total, 4);

        QueryPassRateVO queryPassRateVO = new QueryPassRateVO();
        queryPassRateVO.setFirstVersionPassCount(v1ThroughTotal);
        queryPassRateVO.setSecondVersionPassCount(v2ThroughTotal);
        queryPassRateVO.setThirdVersionPassCount(v3ThroughTotal);
        queryPassRateVO.setTotalCount(total);

        queryPassRateVO.setFirstVersionPassRate(NumberUtil.formatPercent(firstVersionPassRate, 2));
        queryPassRateVO.setSecondVersionPassRate(NumberUtil.formatPercent(secondVersionPassRate, 2));
        queryPassRateVO.setThirdVersionPassRate(NumberUtil.formatPercent(thirdVersionPassRate, 2));

        return queryPassRateVO;
    }

    /**
     * 审核批量打版
     *
     * @param reviewDTO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void review(GoodsReviewDTO reviewDTO) {
        List<SysGoods> goodsList = super.list(new LambdaQueryWrapper<SysGoods>()
                .in(SysGoods::getId, reviewDTO.getGoodsIds())
        );
        if (CollUtil.isEmpty(goodsList)) {
            return;
        }

        goodsList = goodsList.stream().peek(x -> {
            x.setReviewTime(new Date());
            x.setReviewVersion(reviewDTO.getReviewVersion());
            x.setReviewResult(reviewDTO.getReviewResult());
            x.setUpdateBy(SecurityUtils.getUserId());
        }).collect(Collectors.toList());
        super.updateBatchById(goodsList);
    }

    /**
     * 更新商品库存信息
     *
     * @param updateStorageDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStorage(UpdateGoodStorageDTO updateStorageDTO) {
        SysInventoryStorageArchive storageArchive = this.storageArchiveService.getById(updateStorageDTO.getInventoryStorageArchiveId());
        Assert.notNull(storageArchive, "库位档案不存在");

        SysGoods sysGoods = super.getById(updateStorageDTO.getGoodsId());
        Assert.notNull(sysGoods, "商品不存在");

        // 更新数据
        sysGoods.setInventoryStorageArchiveId(updateStorageDTO.getInventoryStorageArchiveId());
        sysGoods.setUpdateBy(SecurityUtils.getUserId());
        super.updateById(sysGoods);
    }

    /**
     * 同步打板信息到mes
     *
     * @param goodsId
     */
    @Override
    public void synchronizedStyle(Long goodsId) {
        SysGoods sysGoods = super.getById(goodsId);
        Assert.notNull(sysGoods, "打板信息不存在");

        //1. 获取款信息
        GoodsDesignInfoVO goodsDesignInfo = this.getGoodsDesignInfo(goodsId);

        //2. 获取报价单信息
        GoodsQuotationSheetVO goodsQuotationSheet = this.getGoodsQuotationSheet(goodsId);

        // 构建接口请求对象
        SynchronizedStyleDTO synchronizedStyleDTO = new SynchronizedStyleDTO();
        synchronizedStyleDTO.setProdName(goodsDesignInfo.getGoodsName());
        synchronizedStyleDTO.setProdno(Convert.toStr(goodsId));
        synchronizedStyleDTO.setRemark(sysGoods.getRemark());
        synchronizedStyleDTO.setStylName(goodsDesignInfo.getSkc());
        synchronizedStyleDTO.setStyleFrom("ERP");
        synchronizedStyleDTO.setStylno(goodsDesignInfo.getSkc());
        synchronizedStyleDTO.setThirdUid(Convert.toStr(goodsId));
        synchronizedStyleDTO.setBrandId(null);
        synchronizedStyleDTO.setMtrlno(null);
        synchronizedStyleDTO.setSeason(null);


        //TODO 2025-11-17 开会讨论说不需要BOM数据
        List<SynchronizedStyleDTO.StyleBom> styleBomlist = new ArrayList<>();
        List<SynchronizedStyleDTO.StyleOper> styleOperlist = new ArrayList<>();
        List<SynchronizedStyleDTO.StylePart> stylePartlist = new ArrayList<>();
        List<SynchronizedStyleDTO.StyleTech> styleTechlist = new ArrayList<>();
        long sortNo = 1; // 加工顺序
        boolean isMainBranch = true;
        for (GoodsQuotationSheetPartDTO part : goodsQuotationSheet.getParts()) {
            // 处理 物料
//            if (CollUtil.isNotEmpty(part.getPartMaterials())) {
//                GoodsQuotationSheetPartMaterialDTO partMaterialDTO = part.getPartMaterials().get(0);
//                for (GoodsMaterialItemDTO material : partMaterialDTO.getMaterials()) {
//                    SynchronizedStyleDTO.StyleBom styleBom = new SynchronizedStyleDTO.StyleBom();
//                    styleBom.setMainMterial(material.getMaterialName().startsWith("面料"));
//                    styleBom.setMtrlcd(material.getSku());
//                    styleBom.setMtrnam(material.getMaterialName());
//                    styleBom.setMtsrnm(material.getTypeName());
//                    styleBom.setMtsrno(null);
//                    styleBom.setPurpos(material.getPartUsed());
//                    styleBom.setUnitnm(material.getUnit());
//                    styleBom.setWstrat(material.getSinglePieceUsage());
//                    styleBomlist.add(styleBom);
//                }
//            }


            // 处理 工序
            GoodsQuotationSheetPartProcessDTO partProcess = part.getPartProcess();
            if (partProcess != null && CollUtil.isNotEmpty(partProcess.getProcessItems())) {
                for (GoodsQuotationSheetPartProcessDTO.ProcessItemVO processItem : partProcess.getProcessItems()) {
                    SynchronizedStyleDTO.StyleOper styleOper = new SynchronizedStyleDTO.StyleOper();
                    styleOper.setOperId(processItem.getProcessName());
                    styleOper.setOperName(processItem.getProcessName());
                    styleOper.setMacType(null);
                    styleOper.setPartId(Convert.toStr(part.getPartId()));
                    styleOper.setPartName(part.getPartLibrary());
                    styleOper.setSortNo(sortNo++);
                    styleOper.setStdPrice(Convert.toDouble(processItem.getWage()));
                    styleOper.setStdmValue(null);
                    styleOper.setWctyCd(null);
                    styleOper.setWctyName(null);
                    styleOperlist.add(styleOper);
                }
            }

            // 处理 部件
            SynchronizedStyleDTO.StylePart stylePart = new SynchronizedStyleDTO.StylePart();
            stylePart.setBrannm(part.getPartLibrary());
            stylePart.setBranno(Convert.toStr(part.getPartId()));
            stylePart.setMainbranch(isMainBranch);
            stylePartlist.add(stylePart);

            // 重新设置主分支
            isMainBranch = false;

            // 处理工艺
            if (CollUtil.isNotEmpty(part.getPartSecondProcesses())) {
                for (GoodsQuotationSheetPartSecondProcessDTO partSecondProcess : part.getPartSecondProcesses()) {
                    SynchronizedStyleDTO.StyleTech styleTech = new SynchronizedStyleDTO.StyleTech();
                    styleTech.setPartId(Convert.toStr(part.getPartId()));
                    styleTech.setPartName(part.getPartLibrary());
                    styleTech.setTechDetail(partSecondProcess.getProcessName());
                    styleTechlist.add(styleTech);
                }
            }
        }

        // 处理款式图片
        List<SynchronizedStyleDTO.StyleDoc> styleDoclist = new ArrayList<>();
        SynchronizedStyleDTO.StyleDoc styleDoc = new SynchronizedStyleDTO.StyleDoc();
        styleDoc.setBustype("款式图片");
        styleDoc.setFilename(FileUtil.getName(sysGoods.getPic()));
        styleDoc.setFiletype(FileUtil.getSuffix(sysGoods.getPic()));
        styleDoc.setFileurl(sysGoods.getPic());
        styleDoclist.add(styleDoc);


        synchronizedStyleDTO.setStyleBomlist(styleBomlist);
        synchronizedStyleDTO.setStyleDoclist(styleDoclist);
        synchronizedStyleDTO.setStyleOperlist(styleOperlist);
        synchronizedStyleDTO.setStylePartlist(stylePartlist);
        synchronizedStyleDTO.setStyleTechlist(styleTechlist);

        this.synchronizedMesService.styleSynchronized(synchronizedStyleDTO);
    }

    /**
     * 根据sku获取商品信息
     *
     * @param sku
     * @return
     */
    @Override
    public SysGoods getGoodsBySku(String sku) {
        SysGoods sysGoods = super.getOne(new LambdaQueryWrapper<SysGoods>()
                .eq(SysGoods::getSkc, sku)
        );
        Assert.notNull(sysGoods, "该SKU对应的商品不存在");
        return sysGoods;
    }


    /**
     * 商品款信息数据校验
     *
     * @param submitDTO
     */
    private void checkGoodsDesignInfo(GoodsDesignInfoSubmitDTO submitDTO) {
        // 校验skc不能重复
        int count = super.count(new LambdaQueryWrapper<SysGoods>().eq(SysGoods::getSkc, submitDTO.getSkc())
                .ne(submitDTO.getId() != null, SysGoods::getId, submitDTO.getId()));
        Assert.isTrue(count == 0, "skc已存在");
    }


}
